package com.fight.strive.sys.utils;

import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import okhttp3.Call;
import okhttp3.FormBody;
import okhttp3.Headers;
import okhttp3.HttpUrl;
import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okhttp3.ResponseBody;
import org.springframework.http.HttpStatus;

import java.io.File;
import java.io.InputStream;
import java.util.Map;
import java.util.Objects;

/**
 * 主要使用okHttp库进行http请求访问的操作
 *
 * @author ZHOUXIANG
 */
@Slf4j
public class OkHttpUtils {

    private static final OkHttpClient client = new OkHttpClient();

    /**
     * okHttp get请求
     */
    public static String get(String url, Map<String, Object> params,
                             Map<String, String> headers) {
        HttpUrl.Builder urlBuilder = Objects.requireNonNull(HttpUrl.parse(url))
                .newBuilder();
        if (ObjectUtils.notNull(params)) {
            params.forEach((key, value) -> urlBuilder
                    .addQueryParameter(key, String.valueOf(value)));
        }
        Request request = new Request.Builder()
                .headers(Headers.of(headers))
                .url(urlBuilder.build())
                .get().build();
        return call(request);
    }

    /**
     * okHttp post提交数据并返回字符串响应
     */
    public static String postForm(String url, Map<String, Object> params,
                                  Map<String, String> headers) {
        FormBody.Builder builder = new FormBody.Builder();
        if (ObjectUtils.notNull(params)) {
            params.forEach((key, value) -> builder.add(key, String.valueOf(value)));
        }
        Request request = new Request.Builder()
                .headers(Headers.of(headers))
                .url(url).post(builder.build())
                .build();
        return call(request);
    }

    /**
     * 提交JSON对象字符串
     *
     * @param url    请求地址
     * @param object 请求参数对象
     * @return 响应字符串
     */
    public static String postJson(String url, Object object, Map<String, String> headers) {
        MediaType type = MediaType.parse("application/json; charset=utf-8");
        String jsonString = JSON.toJSONString(object);
        Request request = new Request.Builder()
                .headers(Headers.of(headers))
                .url(url)
                .post(RequestBody.create(jsonString, type))
                .build();
        return call(request);
    }

    /**
     * MultipartBody 请求多种类型的数据，上传文件
     */
    public static String postMultipart(
            String url, Map<String, Object> params,
            File file, Map<String, String> headers) {
        MultipartBody.Builder builder = new MultipartBody.Builder()
                .setType(MultipartBody.FORM);
        if (ObjectUtils.notNull(params)) {
            params.forEach((key, value) -> builder
                    .addFormDataPart(key, String.valueOf(value)));
        }
        if (ObjectUtils.notNull(file)) {
            builder.addFormDataPart("file", file.getName(),
                    RequestBody.create(file, MediaType.parse("application/octet-stream")));
        }
        Request request = new Request.Builder()
                .url(url)
                .post(builder.build())
                .build();
        return call(request);
    }

    /**
     * 文件下载
     */
    public static InputStream downloadFile(String url) {
        try {
            Request request = new Request.Builder()
                    .get().url(url).build();
            OkHttpClient client = new OkHttpClient();
            Response response = client.newCall(request).execute();
            if (response.code() == HttpStatus.OK.value()) {
                assert response.body() != null;
                return response.body().byteStream();
            } else {
                log.warn("下载文件失败：{}", response.message());
            }
        } catch (Exception e) {
            log.error("OkHttp下载错误", e);
        }
        return null;
    }

    /**
     * 通用请求
     */
    public static String call(Request request) {
        try {
            final Call call = client.newCall(request);
            Response response = call.execute();
            if (response.code() == HttpStatus.OK.value()) {
                ResponseBody body = response.body();
                try {
                    if (ObjectUtils.notNull(body)) {
                        return body.string();
                    }
                } finally {
                    response.close();
                    if (ObjectUtils.notNull(body)) {
                        body.close();
                    }
                }
            } else {
                log.warn("服务器请求失败:{}", response);
            }
            response.close();
        } catch (Exception e) {
            log.error("OkHttp请求错误:{}", e.getMessage());
        }
        return null;
    }
}
